package com.mjk.common.core.jdbc.service.dbconver;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;

import com.mjk.common.core.jdbc.datasource.DynamicDataSource;
import com.mjk.common.core.jdbc.service.dbconver.annotation.BeeConver;
import com.mjk.common.core.jdbc.service.dbconver.bean.BaseConverParams;
import com.mjk.common.core.jdbc.service.dbconver.bean.BaseDbConverBean;
import com.mjk.common.core.jdbc.service.dbconver.bean.BaseDbResultBean;
import com.mjk.common.core.jdbc.service.dbconver.mapper.DbConverMapper;
import com.mjk.common.core.jdbc.service.log.BeeLogContentHolder;
import com.mjk.common.core.jdbc.service.log.model.BeeLogModel;
import com.mjk.common.core.jdbc.service.plus.idbservice.BeeDBService;
import com.mjk.common.core.jdbc.service.plus.wrap.BeeQueryWrapper;
import com.mjk.common.tools.conver.abstractor.SchedledConver;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.scheduled.DynamicScheduledModel;
import com.mjk.common.tools.springextend.BeeApplicationListener;
import com.mjk.common.tools.springextend.BeeSpringBean;
import com.mjk.common.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

@Configuration
public class BaseDbConver extends SchedledConver implements BeeApplicationListener {
	@SuppressWarnings("rawtypes")
	private BeeDBService beeDBService;
	@Autowired
	private DbConverMapper mapper;
	@Autowired
	private BeeLogContentHolder logService;
	/**
	 * 定义任务列表
	 */
	private List<DynamicScheduledModel>  tasks = new ArrayList<>();
	
	public List<DynamicScheduledModel> getTasks() {
		return tasks;
	}

	public void setTasks(List<DynamicScheduledModel> tasks) {
		this.tasks = tasks;
	}

	public void converTarget(Object o) {
		if(o instanceof BaseDbResultBean result){
			if(ObjectUtils.isEmpty(result.getConver())) {//如果没有转化器
				try {
					Map<String,Object> map = (Map<String, Object>) result.getResult();
					List<BaseConverParams> params = GsonUtils.json2List(result.getConverParams(), BaseConverParams.class);
					DynamicDataSource.setDatabaseType(result.getTargetDataSoucre());
					if(!CollectionUtils.isEmpty(params)) {
							Map<String,Object>  converMap = new HashMap<>();
							for(BaseConverParams param : params) {
								converMap.put(param.getTarget(), MapUtils.getString(map, param.getSource()));
							}
							List<Map<String,Object>> tmpResult = mapper.executeSql(result.getConditionParams(), converMap);
							if(ObjectUtils.isNotEmpty(result.getConditionParams())) {
								if(CollectionUtils.isEmpty(tmpResult))
									mapper.executeSql(result.getTargetSql(), converMap);
							}else {//如果没有条件，不进行判断
								mapper.executeSql(result.getTargetSql(), converMap);
							}
					}else {
						if(ObjectUtils.isNotEmpty(result.getTargetSql()))
							mapper.executeSql(result.getTargetSql(), new HashMap<>());
					}
				}catch(Exception e) {//记录错误日志，不做其他事情
					//BeeLogContentHolder.needLog.set(true);
					logService.put(new BeeLogModel(result.getId() + "", "2", GsonUtils.bean2Json(result), ExceptionUtil.getMessage(e)));
				}
			}else {
				String sql = result.getConver().getTargetSql(result);
				if(ObjectUtils.isNotEmpty(sql)){
					beeDBService.excuteSql(sql);
				}
			}
		}
	}
	
	@SuppressWarnings({ "resource", "rawtypes" })
	public void converSource(Object obj) {
		try{
			if(obj instanceof BaseDbConverBean bean){
				ITableConver conver = (ITableConver) BeeSpringBean.getBean(ClassUtil.loadClass(bean.getConver()));
				DynamicDataSource.setDatabaseType(bean.getSourceDataSource());
				Page page = PageMethod.startPage(1, bean.getPageSize());
				if(ObjectUtils.isEmpty(bean.getSourceSql())) {
					beeDBService.excuteSql(conver.getSourceSql());
				}else {
					beeDBService.excuteSql(bean.getSourceSql());
				}
				//第一次调用 返回分页信息
				for(Object tmp : page.getResult()){
					BaseDbResultBean result = new BaseDbResultBean();
					result.setResult(tmp);
					result.setId(bean.getId());
					result.setConver(conver);
					result.setTargetDataSoucre(bean.getTargetDataSource());
					result.setConverParams(bean.getConverParams());
					result.setConditionParams(bean.getConditionParams());
					result.setTargetSql(bean.getTargetSql());
					queue.put(result);
				}
				//第二次参数开始 页数传入从2 开始
				for(int i = 2;i<=page.getPages();i++){
					page = PageMethod.startPage(i, bean.getPageSize());
					beeDBService.excuteSql(bean.getSourceSql());
					for(Object tmp : page.getResult()){//第一次调用 返回分页信息
						BaseDbResultBean result = new BaseDbResultBean();
						result.setId(bean.getId());
						result.setResult(tmp);result.setConver(conver);
						result.setTargetDataSoucre(bean.getTargetDataSource());
						result.setConverParams(bean.getConverParams());
						result.setConditionParams(bean.getConditionParams());
						result.setTargetSql(bean.getTargetSql());
						queue.put(result);
					}
				}
			}
		}catch(Exception e){
			BaseDbConverBean bean = (BaseDbConverBean)obj;
			//BeeLogContentHolder.needLog.set(true);
			logService.put(new BeeLogModel(bean.getId() + "", "2", GsonUtils.bean2Json(bean), ExceptionUtil.getMessage(e)));
			Thread.currentThread().interrupt();
		}
	}
	
	@Override
	protected List<DynamicScheduledModel> listTaskInfo() {
		return tasks;
	}
	
	@Override
	protected void doProcess(DynamicScheduledModel model) {
		BaseDbConverBean bean = GsonUtils.json2Bean(model.getTaskParams(), BaseDbConverBean.class);
		converSource(bean);
	}
	
	@Override
	public void doApplicationEvent(ContextRefreshedEvent event) {

		beeDBService = event.getApplicationContext().getBean(BeeDBService.class);
		//获取beeconver的实例
		Map<String,Object> maps = event.getApplicationContext().getBeansWithAnnotation(BeeConver.class);
		for(Entry<String,Object> entry : maps.entrySet()){
			if(entry.getValue() instanceof ITableConver instanc){
				BaseDbConverBean bean = new BaseDbConverBean();
				BeeConver conver = AopTargetUtils.getTarget(entry.getValue()).getClass().getAnnotation(BeeConver.class);
				bean.setCorn(conver.corn());
				bean.setConverName(conver.converName());
				bean.setSourceDataSource(conver.sourceDataSource());
				bean.setTargetDataSource(conver.targetDataSource());
				bean.setSourceSql(instanc.getSourceSql());
				bean.setStatus(conver.status()+"");
				bean.setConver(instanc.getClass().getName());
				bean.setPageSize(conver.pageSize());
				BeeQueryWrapper wrapper = new BeeQueryWrapper(bean);
				wrapper.eq(BaseDbConverBean::getConverName,conver.converName());
				List<BaseDbConverBean> convers = beeDBService.findManyByWrapper(wrapper);
				if(CollectionUtils.isEmpty(convers)){
					beeDBService.insert(bean);
				}else{
					bean.setId(convers.get(0).getId());
					bean.setStatus(null);
					beeDBService.update(wrapper);
				}
			}
		}
		BeeQueryWrapper wrapper = new BeeQueryWrapper(new BaseDbConverBean());
		List<BaseDbConverBean> convers = beeDBService.findManyByWrapper(wrapper);
		for(BaseDbConverBean task : convers) {
			tasks.add(DynamicScheduledModel.builder()
					.id(task.getId()+"")
					.cron(task.getCorn())
					.isValid("1".equals(task.getStatus()))
					.taskParams(GsonUtils.bean2Json(task))
					.build()
					);
		}
	}
}
